四种接口类型
到目前为止,我们主要讨论的是同时拥有输入和输出组件的 Gradio 应用。但实际上,gradio.Interface
类可以灵活地处理四种不同类型的交互模式。这取决于你如何设置 inputs
和 outputs
参数。
理解这四种类型可以帮助你为不同场景构建更合适的 UI:
- 标准演示 (Standard Demos):具有独立的输入和输出组件。
- 仅输出演示 (Output-only Demos):没有输入组件,只有输出组件。
- 仅输入演示 (Input-only Demos):只有输入组件,没有输出组件。
- 统一演示 (Unified Demos):输入和输出是同一个组件。
根据演示类型的不同,用户界面 (UI) 也会略有差异。例如,仅输出的演示通常只有一个 "Generate" (生成) 按钮,而没有 "Clear" (清除) 或 "Submit" (提交) 按钮(除非函数本身不需要任何触发)。
1. 标准演示 (Standard Demos)
这是最常见的类型,你的函数接收一些输入,并产生一些输出,输入和输出通过不同的组件展示。
python
import gradio as gr
import numpy as np
from PIL import Image
# 示例函数:对图像应用棕褐色滤镜
def sepia_filter(input_img_pil):
# input_img_pil 应该是一个 PIL Image 对象
if input_img_pil is None:
return None
input_img = np.array(input_img_pil)
sepia_matrix = np.array([
[0.393, 0.769, 0.189],
[0.349, 0.686, 0.168],
[0.272, 0.534, 0.131]
])
sepia_img_array = input_img.dot(sepia_matrix.T)
sepia_img_array /= sepia_img_array.max() # 归一化
sepia_img_array = np.clip(sepia_img_array, 0, 1) # 确保值在0-1之间
return Image.fromarray((sepia_img_array * 255).astype(np.uint8))
demo_standard = gr.Interface(
fn=sepia_filter,
inputs=gr.Image(type="pil", label="上传原始图片"),
outputs=gr.Image(type="pil", label="棕褐色滤镜效果"),
title="图像棕褐色滤镜",
description="上传一张图片,应用棕褐色滤镜。",
examples=[["gradio_logo.png"]] # 请确保你有一个名为 gradio_logo.png 的图片或替换为有效路径
)
# demo_standard.launch() # 在本地取消注释以运行
2. 仅输出演示 (Output-only Demos)
当你的函数不需要任何用户输入,而是直接生成一些结果时(例如,一个随机数生成器、一个预设的文本生成器或一个无条件的图像生成模型),你可以使用仅输出的演示。只需将 inputs
参数设置为 None
。
python
import gradio as gr
import random
import time
# 模拟一个不需要输入的图像生成函数
def generate_random_image_url():
time.sleep(1) # 模拟处理时间
image_urls = [
"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
"https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=386&q=80",
"https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80",
]
# 对于实际的图像生成,这里会返回图像数据 (PIL, numpy, 或路径)
# 这里我们用 gr.HTML 来显示网络图片作为示例
selected_url = random.choice(image_urls)
return f'<img src="{selected_url}" alt="Generated Image" width="300" />'
demo_output_only = gr.Interface(
fn=generate_random_image_url,
inputs=None, # 没有输入
outputs=gr.HTML(label="随机生成的图片 (来自 Unsplash)"), # 使用HTML组件显示网络图片
title="随机图片生成器 (模拟)",
description="点击生成按钮,随机显示一张来自 Unsplash 的图片。"
)
# demo_output_only.launch()
3. 仅输入演示 (Input-only Demos)
如果你的应用接收用户输入,但其主要目的是执行一个动作而不是返回并在界面上显示一个明确的输出(例如,将数据保存到数据库、发送邮件、控制一个硬件设备等),你可以使用仅输入的演示。只需将 outputs
参数设置为 None
。
python
import gradio as gr
import os
from datetime import datetime
# 确保 'user_uploads' 文件夹存在
if not os.path.exists("user_uploads"):
os.makedirs("user_uploads")
def save_text_to_file(text_content, filename_prefix):
if not text_content:
return "内容不能为空!" # 可以通过打印或日志来提示,因为没有输出组件
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"{filename_prefix}_{timestamp}.txt"
filepath = os.path.join("user_uploads", filename)
try:
with open(filepath, "w", encoding="utf-8") as f:
f.write(text_content)
print(f"文件已保存到: {filepath}") # 在后端打印确认信息
return f"文件已成功保存为: {filename}" # 虽然outputs=None,但可以返回一个值给flagging等
except Exception as e:
print(f"保存文件时出错: {e}")
return f"保存文件失败: {e}"
demo_input_only = gr.Interface(
fn=save_text_to_file,
inputs=[
gr.Textbox(label="输入文本内容", lines=5, placeholder="在此处输入任何文本..."),
gr.Textbox(label="文件名前缀", value="我的笔记")
],
outputs=None, # 没有输出组件,但函数仍可返回值用于flagging或API
title="文本保存工具",
description="输入内容和文件名前缀,点击提交后文本将保存到服务器的 'user_uploads' 文件夹下。",
allow_flagging="never"
)
# demo_input_only.launch()
4. 统一演示 (Unified Demos)
在统一演示中,输入和输出使用同一个组件。这意味着函数处理输入后,其返回结果会更新(或替换)原始输入组件的内容。这对于文本自动补全、图像编辑(原地修改)等场景非常有用。
python
import gradio as gr
# 简单的文本处理函数:将文本转为大写并添加感叹号
def process_text_inplace(current_text):
if not current_text:
return ""
return current_text.upper() + "!!!"
# 使用同一个 Textbox 实例作为输入和输出
shared_textbox = gr.Textbox(label="输入或查看处理后的文本", lines=3)
demo_unified = gr.Interface(
fn=process_text_inplace,
inputs=shared_textbox, # 同一个组件
outputs=shared_textbox, # 同一个组件
title="文本原地处理",
description="输入一些文本,点击提交后,文本框内容将被处理并更新。",
live=False # 在这种模式下,通常 live=False 更合适,用户显式提交
)
# demo_unified.launch()
如果以上四种类型仍然不能满足你的复杂布局或交互需求,那么你就需要转向使用更灵活的 gradio.Blocks
API 来构建你的应用了。